using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Xml.Serialization;
using System.IO;
using System.Threading;

namespace YATC
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //meine Audio Library
        private AudioLibrary audioLibrary;
        //Sonstiges
        public SpriteFont gameFont;
        private GameScene currentScene;
        private StartScene startScene;
        private ActionScene actionScene;
        private EnterDialog enterDialog;
        private HighScore highScore;
        private OptionScene optionScene;
        private CreditScene creditScene;
        private question _question;
        public Model model;
        public Model[] shape;
        private KeyboardState old;
        public Camera camera;
        public Texture2D[] _text;
        public Model bordure;
        public Texture2D bord;
        private Model goText;
        private Texture2D enterBack;
        private Texture2D menuBack;
        private Model gpText;
        private Model title;
        private Texture2D highBack;
        private Model[] menu;
        private Texture2D quest;
        private Texture2D optionBack,volBar,resetB,resetB1;
        //Parallele THread, damit Prozessor nicht auf 100 %
        Thread loadingContentThread;
        bool bol = true;
        //Fuer das Credit-Menue
        private SpriteFont fontBold;
        private SpriteFont font;


        private GamePadState oldGamePadState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferredBackBufferWidth = 1024;
            graphics.PreferredBackBufferHeight = 768;
            old = Keyboard.GetState();

            camera = new Camera(new Vector3(0f, -1.98f, 30.72f), 0.01f, 0.095f, 10);

            Mouse.SetPosition(200, 200);
            _text = new Texture2D[12];

            menu = new Model[5];
            shape = new Model[8];

			var ser = new XmlSerializer(typeof(float));
			var r = new StreamReader(@".\\Content\Setting.xml");
			Score.volume = (float)ser.Deserialize(r);
			r.Close();


            //XBOX
            oldGamePadState = GamePad.GetState(PlayerIndex.One);
        }



        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            audioLibrary = new AudioLibrary(this);
            Services.AddService(typeof (AudioLibrary), audioLibrary);            
            gameFont = Content.Load<SpriteFont>("Font");Score.percentage++;
            menuBack = Content.Load<Texture2D>("menu_back");Score.percentage++;
            volBar = Content.Load<Texture2D>("volBar"); Score.percentage++;
            //Ladeprozess
            loadingContentThread = new Thread(
                new ThreadStart(
                    delegate
                        {
                            Exiting += delegate
                            {
                                if (loadingContentThread != null &&
                                    loadingContentThread.IsAlive)
                                {
                                    loadingContentThread.Abort();
                                }
                            };
                            
                            #region Load All the Content


                            audioLibrary.LoadContent(Content);
                            model = Content.Load<Model>("Cube"); Score.percentage++;
                            bordure = Content.Load<Model>("bordur"); Score.percentage++;
                            shape[0] = Content.Load<Model>("blocks\\1"); Score.percentage++;
                            shape[1] = Content.Load<Model>("blocks\\2"); Score.percentage++;
                            shape[2] = Content.Load<Model>("blocks\\3"); Score.percentage++;
                            shape[3] = Content.Load<Model>("blocks\\4"); Score.percentage++;
                            shape[4] = Content.Load<Model>("blocks\\5"); Score.percentage++;
                            shape[5] = Content.Load<Model>("blocks\\6"); Score.percentage++;
                            shape[6] = Content.Load<Model>("blocks\\7"); Score.percentage++;
                            shape[7] = Content.Load<Model>("blocks\\bord"); Score.percentage++;

                            bord = Content.Load<Texture2D>("sky"); Score.percentage++;
                            goText = Content.Load<Model>("Text\\go"); Score.percentage++;
                            gpText = Content.Load<Model>("Text\\gp"); Score.percentage++;
                            enterBack = Content.Load<Texture2D>("back"); Score.percentage++;

                            title = Content.Load<Model>("Text\\title"); Score.percentage++;
                            highBack = Content.Load<Texture2D>("highs"); Score.percentage++;
                            quest = Content.Load<Texture2D>("ques"); Score.percentage++;
                            optionBack = Content.Load<Texture2D>("optionBack"); Score.percentage++;
                            resetB = Content.Load<Texture2D>("resetb"); Score.percentage++;
                            resetB1 = Content.Load<Texture2D>("resetb1"); Score.percentage++;

                            menu[0] = Content.Load<Model>("Text\\ng"); Score.percentage++;
                            menu[1] = Content.Load<Model>("Text\\hs"); Score.percentage++;
                            menu[2] = Content.Load<Model>("Text\\op"); Score.percentage++;
                            menu[3] = Content.Load<Model>("Text\\cr"); Score.percentage++;
                            menu[4] = Content.Load<Model>("Text\\ex"); Score.percentage++;

                            font = Content.Load<SpriteFont>("Cfont"); Score.percentage++;
                            fontBold = Content.Load<SpriteFont>("CfontB"); Score.percentage++;

                            #region textures
                            _text[0] = Content.Load<Texture2D>("textures\\0"); Score.percentage++;
                            _text[1] = Content.Load<Texture2D>("textures\\1"); Score.percentage++;
                            _text[2] = Content.Load<Texture2D>("textures\\2"); Score.percentage++;
                            _text[3] = Content.Load<Texture2D>("textures\\3"); Score.percentage++;
                            _text[4] = Content.Load<Texture2D>("textures\\4"); Score.percentage++;
                            _text[5] = Content.Load<Texture2D>("textures\\5"); Score.percentage++;
                            _text[6] = Content.Load<Texture2D>("textures\\6"); Score.percentage++;
                            _text[7] = Content.Load<Texture2D>("textures\\7"); Score.percentage++;
                            _text[8] = Content.Load<Texture2D>("textures\\8"); Score.percentage++;
                            _text[9] = Content.Load<Texture2D>("textures\\9"); Score.percentage++;
                            _text[10] = Content.Load<Texture2D>("textures\\tr"); Score.percentage++;
                            _text[11] = Content.Load<Texture2D>("textures\\white"); Score.percentage++;
                            #endregion

                            #endregion
                            
                            loadingContentThread = null;
                        }
                    )
                )
            {
                Name = "Lade Thread",
                Priority = ThreadPriority.Normal,
            };

        	loadingContentThread.Start();

 
           
        }

        private void Declare()
        {
            startScene = new StartScene(this, title, menu);
            Components.Add(startScene);

            actionScene = new ActionScene(this, gameFont, model, bordure, shape, goText, gpText);
            Components.Add(actionScene);
            MediaPlayer.Stop();

            enterDialog = new EnterDialog(this, gameFont);
            Components.Add(enterDialog);

            highScore = new HighScore(this);
            Components.Add(highScore);

            //TOPLISTE
            var ser = new XmlSerializer(typeof(List<Player>));
            var w = new StreamReader(@".\\Content\SaveGame.xml");
            highScore.List = (List<Player>)ser.Deserialize(w);
            w.Close();

            _question = new question(this);
            Components.Add(_question);

            optionScene = new OptionScene(this);
            Components.Add(optionScene);

            creditScene = new CreditScene(this,title);

            currentScene = startScene;
            currentScene.Show();
        }

   
        protected override void Update(GameTime gameTime)
        {
           
            var curS = Keyboard.GetState();
            var curX = GamePad.GetState(PlayerIndex.One);

            // Beenden
            if ((curS.IsKeyDown(Keys.Escape) && old.IsKeyUp(Keys.Escape)) || ((curX.Buttons.B == ButtonState.Pressed) && (oldGamePadState.Buttons.B == ButtonState.Released)))
                if (currentScene == startScene)
                    Exit();
                else
                    if (currentScene == actionScene && !actionScene.IsGameOver && !actionScene.IsGamePaused)
                        ShowScene(_question);
                    else if (currentScene == optionScene)
                        ShowScene(startScene);
                    else if (currentScene == creditScene)
                        ShowScene(startScene);
                    else if (currentScene == highScore)
                        ShowScene(startScene);

            
            if ((curS.IsKeyDown(Keys.Enter) && old.IsKeyUp(Keys.Enter)) || (curX.Buttons.X == ButtonState.Pressed && oldGamePadState.Buttons.X == ButtonState.Released))
                if (currentScene == actionScene)
                {
                    if (actionScene.IsGameOver)
                        ShowScene(enterDialog);
                }
                else if(currentScene == enterDialog)
                {
                    var p = new Player
                                {
                                    name = (enterDialog.Text == "" ? "NoBody" : enterDialog.Text),
                                    score = Score.score,
                                    level = Score.level,
                                    time = Score.time
                                };

                    highScore.Add(p);
                    ShowScene(highScore);
                                        
                }
                else if(currentScene == highScore)
                    ShowScene(startScene);
                else if(currentScene == startScene)
                {
                    switch(startScene.Selected)
                    {
                        case 0:
                            actionScene.Initialize();
                            ShowScene(actionScene); 
                            break;
                        case 1:
                            ShowScene(highScore);
                            break;
                        case 2:
                            ShowScene(optionScene);
                            break;
                        case 3:
                            ShowScene(creditScene);
                            creditScene.Initialize();
                            break;
                        case 4:
                            Exit();
                            break;
                    }
                                                           
                }
                else if(currentScene == optionScene)
                    ShowScene(startScene);
                else if(currentScene == creditScene)
                    ShowScene(startScene);



            if ((curS.IsKeyDown(Keys.N) && old.IsKeyUp(Keys.N)) || (curX.Buttons.A == ButtonState.Pressed && oldGamePadState.Buttons.A == ButtonState.Released))
                if (currentScene == _question) ShowScene(actionScene);

            if ((curS.IsKeyDown(Keys.J) && old.IsKeyUp(Keys.J)) || (curX.Buttons.Y == ButtonState.Pressed && oldGamePadState.Buttons.Y == ButtonState.Released))
                if (currentScene == _question) ShowScene(startScene);

              

            if(curS.IsKeyDown(Keys.F5) && old.IsKeyUp(Keys.F5))
                graphics.ToggleFullScreen();
            
            
            
            old = curS;

            oldGamePadState = curX;
          

            base.Update(gameTime);
        }

        

        private void ShowScene(GameScene scene)
        {
            currentScene.Hide();
            currentScene = scene;
            currentScene.Show();
        }



        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);          
            if (loadingContentThread != null &&
                loadingContentThread.IsAlive)
            {
                spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null);
                spriteBatch.Draw(menuBack,new Rectangle(0,0,menuBack.Width,menuBack.Height),Color.White );
                spriteBatch.DrawString(gameFont, "Laden   " + (Score.percentage * 100 / 51) + "%" /*+ "  "+Score.percentage*/, new Vector2(460, 384), new Color(255, 255, 255));
                spriteBatch.Draw(volBar,new Rectangle(425,420,(Score.percentage*209)/51,volBar.Height),Color.White );
                spriteBatch.End();
                bol = true;
            }
            else
            {
                if (bol)
                {
                    bol = false;
                    Declare();
                }
                spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null);

                if (currentScene == actionScene)
                {
                    spriteBatch.Draw(bord, new Vector2(0, 0), new Rectangle(0, 0, bord.Width, bord.Height), Color.White);
                    spriteBatch.DrawString(gameFont, "Punkte : " + Score.score, new Vector2(800, 180),
                                           new Color(255, 255, 255));
                    spriteBatch.DrawString(gameFont, "Reihen uebrig : " + Score.lines, new Vector2(800, 210),
                                           new Color(255, 255, 255));
                    spriteBatch.DrawString(gameFont, "Level : " + Score.level, new Vector2(800, 240),
                                           new Color(255, 255, 255));
                    spriteBatch.DrawString(gameFont, "Zeit: " + actionScene.Time.ToString(), new Vector2(800, 270),
                                           new Color(255, 255, 255));

                }
                else if (currentScene == startScene)
                {
                    spriteBatch.Draw(menuBack, new Rectangle(0, 0, menuBack.Width, menuBack.Height), Color.White);
                }
                else if (currentScene == enterDialog)
                {
                    spriteBatch.Draw(enterBack, new Rectangle(0, 0, enterBack.Width, enterBack.Height), Color.White);

                    spriteBatch.DrawString(gameFont, enterDialog.Text, new Vector2(410, 386), Color.Black);
                }
                else if (currentScene == highScore)
                {
                    spriteBatch.Draw(highBack, new Rectangle(0, 0, highBack.Width, highBack.Height), Color.White);
                    if (Mouse.GetState().X > 866 && Mouse.GetState().X < (resetB.Width + 866) && Mouse.GetState().Y > 705 &&
                    Mouse.GetState().Y < (resetB.Height + 705))
                    {
                        spriteBatch.Draw(resetB1, new Vector2(866, 705),
                                         new Rectangle(0, 0, resetB1.Width, resetB1.Height), Color.White);
                        if (Mouse.GetState().LeftButton == ButtonState.Pressed)
                            highScore.Reset();
                    }
                    else spriteBatch.Draw(resetB, new Vector2(866, 705), new Rectangle(0, 0, resetB.Width, resetB.Height), Color.White);

                    
                    var posi = new Vector2(48, 115);
                    for (int i = 0; i < (highScore.List.Count > 10 ? 10 : highScore.List.Count); i++)
                    {
                        spriteBatch.DrawString(gameFont, (i + 1).ToString(), posi, new Color(255, 255, 255));
                        posi.X += 115;
                        spriteBatch.DrawString(gameFont, highScore.List[i].name, posi, new Color(255, 255, 255));
                        posi.X += 212;
                        spriteBatch.DrawString(gameFont, highScore.List[i].score.ToString(), posi,
                                               new Color(255, 255, 255));
                        posi.X += 230;
                        spriteBatch.DrawString(gameFont, highScore.List[i].level.ToString(), posi,
                                               new Color(255, 255, 255));
                        posi.X += 231;
                        spriteBatch.DrawString(gameFont, highScore.List[i].time.ToString(), posi,
                                               new Color(255, 255, 255));
                        posi.Y += 50;
                        posi.X = 50;
                    }
                }
                else if (currentScene == _question)
                    spriteBatch.Draw(quest, new Rectangle(0, 0, quest.Width, quest.Height), Color.White);
                else if (currentScene == optionScene)
                {
                    spriteBatch.Draw(optionBack, new Rectangle(0, 0, optionBack.Width, optionBack.Height),
                                     Color.White);
                    spriteBatch.Draw(volBar, new Vector2(550, 224),
                                     new Rectangle(0, 0, (int) optionScene.VolBar, volBar.Height), Color.White);
                }
                else if(currentScene == creditScene)
                {
                    creditScene._Update(gameTime);
					//var line = 
                	var space = creditScene.Textposition.Y;
                	spriteBatch.DrawString(fontBold, "Code and Programing", new Vector2((Window.ClientBounds.Width - fontBold.MeasureString("Game Programing").X) / 2 - 20, space), Color.White);
                    spriteBatch.DrawString(font, "zipfelQ", new Vector2((Window.ClientBounds.Width - font.MeasureString("zipfelQ").X) / 2, space + fontBold.LineSpacing), Color.White);
                    spriteBatch.DrawString(fontBold, "Art, 3D Modeling", new Vector2((Window.ClientBounds.Width - fontBold.MeasureString("Art, 3D Modeling").X) / 2, space + 90), Color.White);
                    spriteBatch.DrawString(font, "zipfelQ", new Vector2((Window.ClientBounds.Width - font.MeasureString("zipfelQ").X) / 2, space + fontBold.LineSpacing + 90), Color.White);

					spriteBatch.DrawString(fontBold, "Game Design", new Vector2((Window.ClientBounds.Width - fontBold.MeasureString("Game Design").X) / 2, space + 180), Color.White);
                    spriteBatch.DrawString(font, "zipfelQ", new Vector2((Window.ClientBounds.Width - font.MeasureString("zipfelQ").X) / 2, space + fontBold.LineSpacing + 180), Color.White);
                    
					spriteBatch.DrawString(fontBold, "Sounds and Music", new Vector2((Window.ClientBounds.Width - fontBold.MeasureString("Sounds and Music").X) / 2, space + 270), Color.White);
                    spriteBatch.DrawString(font, "Tetris sounds", new Vector2((Window.ClientBounds.Width - font.MeasureString("Tetris sounds").X) / 2, space + fontBold.LineSpacing + 270), Color.White);
                  
                    spriteBatch.DrawString(fontBold, "Game Testers", new Vector2((Window.ClientBounds.Width - fontBold.MeasureString("Game Testers").X) / 2, space + 360), Color.White);
                    spriteBatch.DrawString(font, "zipfelQ", new Vector2((Window.ClientBounds.Width - font.MeasureString("zipfelQ").X) / 2, space + fontBold.LineSpacing + 360), Color.White);
                    
                    spriteBatch.DrawString(fontBold, "--", new Vector2((Window.ClientBounds.Width - fontBold.MeasureString("--").X) / 2, space + 430), Color.White);
                   
                   
                    if(creditScene.Stop())                                                                                                                                      
                        ShowScene(startScene);
                }
                spriteBatch.End();
                base.Draw(gameTime);
            }
            

        }

       
    }
}
